package main

import (
	"fmt"
	"go_tutorial/ch11/new_pkg"
	"unsafe"
)

func main() {
	//go语言不支持面向对象
	//面向对象的三个基本特征:1.封装 2.继承 3.多态  4.方法重载 5.抽象基类
	//struct go
	//1.实例化--kv形式
	var c new_pkg.Course = new_pkg.Course{
		"django",
		100,
		"https://www.imooc.com",
	}
	fmt.Println(c)
	//访问
	fmt.Println(c.Url, c.Price, c.Name)

	//大小写在go语言中的重要性
	//一个包中的变量或者是结构体首字母是小写，那么会对另外一个包不可见
	//结构体定义的名称以及属性首字母大写很重要

	//2.第二种实例化方式-顺序形式
	c2 := new_pkg.Course{"java", 10, "https://www.baidu.com"}
	fmt.Println(c2.Url, c2.Price, c2.Name)

	//3.如果一个指向结构体的指针,通过结构体指针获取对象的值
	c3 := &new_pkg.Course{"python", 100, "laimao"}
	fmt.Println(c3)
	fmt.Println((*c3).Price)
	//go语言实际上在借鉴动态语言的特性
	//另外一个根本原因  --go语言的指针是受限的
	fmt.Println(c3.Price, c3.Name, c3.Url) //这里其实是一个Go语言的语法糖 go语言内部会将c3.Price 转化成(*c3).Price

	//4.零值 如果不给结构体赋值,go语言会默认给每个字段采用模式值
	c4 := new_pkg.Course{}
	fmt.Println(c4.Price)

	//5.多种零值初始化方式
	var c5 new_pkg.Course = new_pkg.Course{}
	var c6 new_pkg.Course
	var c7 *new_pkg.Course = new(new_pkg.Course)
	var c8 *new_pkg.Course = &new_pkg.Course{}
	fmt.Println("零值初始化")
	fmt.Println(c5.Price)
	fmt.Println(c6.Price)
	fmt.Println(c7.Price)
	fmt.Println(c8.Price)

	//6.结构体是值类型
	c9 := new_pkg.Course{"java", 10, "https://www.baidu.com"}
	c10 := c9
	fmt.Println(c9)
	fmt.Println(c10)
	c9.Price = 200
	fmt.Println(c9)
	fmt.Println(c10)

	//go语言中的struct无处不在
	//7.结构体的大小，占用内存的大小，可以使用sizeof 来查看对象占用的类型
	fmt.Println(unsafe.Sizeof(1))
	fmt.Println(unsafe.Sizeof(""))
	fmt.Println(unsafe.Sizeof(c10))

	//8.slice的大小
	type slice struct {
		array unsafe.Pointer
		len   int
		cap   int
	}
	// 字符串
	//go语言string的本质 其实string是一个结构体
	//type string struct {
	//	Data uintptr //指针占8个长度
	//	Len  int     //长度64位系统占8个长度
	//}
	//
	s := []string{"django", "java", "scrapy", "flask"}
	fmt.Println("切片占用的内存", unsafe.Sizeof(s))

	m1 := map[string]string{
		"hcj1": "sunck1",
		"hcj2": "sunck2",
		"hcj3": "sunck3",
		"hcj4": "sunck4",
	}
	fmt.Println(unsafe.Sizeof(m1))

	//结构体方法 ,达到了封装数据和封装方法的效果
	c11 := new_pkg.Course{"java", 10, "https://www.baidu.com"}
	c11.SetPrice(200) //修改c11中的price?为什么呢? 语法糖 函数参数的传递是怎么传递的？结构体是值传递
	(&c11).SetPrice(200)
	c11.PrintCourseInfo()
	//结构体的接收者有两种形式 1.值传递  2.指针传递 如果你想改结构体的值 如果结构体的数据很大
	// go语言不支持继承 但是有办法达到同样得效果 组合
}
